package com.snail.clouds.storage;

import com.snail.clouds.storage.auth.LoginCredentials;
import com.snail.clouds.storage.auth.PersistentLoginInfo;
import com.snail.clouds.storage.core.AbstractStorageClient;
import com.snail.clouds.storage.entity.AccountInfo;
import com.snail.clouds.storage.entity.CloudFile;
import com.snail.clouds.storage.entity.TrashItem;
import com.snail.clouds.storage.exception.AuthException;
import com.snail.clouds.storage.exception.CloudStorageException;
import com.snail.clouds.storage.exception.FileException;
import com.snail.clouds.storage.factory.StorageClientFactory;

import java.util.List;
import java.util.function.BiConsumer;

/**
 * 云存储统一客户端入口
 * 使用者只需要引用此类即可使用所有云存储功能
 */
public class StorageClient {

    private AbstractStorageClient client;

    /**
     * 私有构造函数，防止直接实例化
     */
    private StorageClient() {
    }

    /**
     * 创建指定类型的云存储客户端
     *
     * @param providerType 云存储提供商类型
     * @return StorageClientFacade 实例
     */
    public static StorageClient createClient(StorageClientFactory.ProviderType providerType) {
        StorageClient facade = new StorageClient();
        facade.client = StorageClientFactory.createClient(providerType);
        return facade;
    }

    /**
     * 检查是否已登录
     *
     * @return 是否已登录
     */
    public boolean isLoggedIn() {
        return client.isLoggedIn();
    }

    /**
     * 触发登录接口（第一阶段）
     *
     * @param credentials 登录凭据
     * @return 登录会话标识符
     * @throws AuthException 登录触发失败
     */
    public String triggerLogin(LoginCredentials credentials) throws AuthException {
        return client.triggerLogin(credentials);
    }

    /**
     * 检测登录状态接口（第二阶段）
     *
     * @param sessionId 登录会话标识符
     * @return 登录成功时返回持久化信息，否则返回null
     * @throws AuthException 检查登录状态失败
     */
    public PersistentLoginInfo checkLoginStatus(String sessionId) throws AuthException {
        return client.checkLoginStatus(sessionId);
    }

    /**
     * 登录缓存信息序列化成字符串的接口（第三阶段）
     *
     * @return 序列化后的登录信息字符串
     * @throws AuthException 序列化失败
     */
    public String serializeLoginInfo() throws AuthException {
        return client.serializeLoginInfo();
    }

    /**
     * 登录接口恢复接口（第四阶段）
     *
     * @param serializedInfo 序列化后的登录信息字符串
     * @return 恢复是否成功
     * @throws AuthException 恢复登录失败
     */
    public boolean restoreLoginFromString(String serializedInfo) throws AuthException {
        return client.restoreLoginFromString(serializedInfo);
    }

    /**
     * 刷新访问令牌
     *
     * @return 是否刷新成功
     * @throws AuthException 刷新token失败
     */
    public boolean refreshToken() throws AuthException {
        return client.refreshToken();
    }

    /**
     * 获取账户信息
     *
     * @return 账户信息
     * @throws AuthException 未登录
     */
    public AccountInfo getAccountInfo() throws AuthException, CloudStorageException {
        return client.getAccountInfo();
    }

    /**
     * 列出文件
     *
     * @param folderId 文件夹ID，根目录ID由上游使用方定义
     * @return 文件列表
     * @throws AuthException 未登录
     * @throws FileException 文件夹不存在
     */
    public List<CloudFile> listFiles(String folderId) throws AuthException, FileException, CloudStorageException {
        return client.listFiles(folderId);
    }

    /**
     * 创建文件夹
     *
     * @param name     文件夹名称
     * @param parentId 父文件夹ID，根目录ID由上游使用方定义
     * @return 创建的文件夹信息
     * @throws AuthException 未登录
     * @throws FileException 父文件夹不存在或配额已满
     */
    public CloudFile createFolder(String name, String parentId) throws AuthException, FileException, CloudStorageException {
        return client.createFolder(name, parentId);
    }

    /**
     * 上传文件
     *
     * @param fileName         文件名
     * @param fileData         文件数据
     * @param parentId         父文件夹ID，根目录ID由上游使用方定义
     * @param overwrite        是否覆盖同名文件
     * @param progressCallback 进度回调函数
     * @return 上传后的文件信息
     * @throws AuthException         未登录
     * @throws FileException         父文件夹不存在
     * @throws CloudStorageException 配额已满或网络错误
     */
    public CloudFile uploadFile(
            String fileName,
            byte[] fileData,
            String parentId,
            boolean overwrite,
            BiConsumer<Integer, Integer> progressCallback
    ) throws AuthException, FileException, CloudStorageException {
        return client.uploadFile(fileName, fileData, parentId, overwrite, progressCallback);
    }

    /**
     * 删除文件
     *
     * @param fileId 文件ID
     * @throws AuthException 未登录
     * @throws FileException 文件不存在
     */
    public void deleteFile(String fileId) throws AuthException, FileException {
        client.deleteFile(fileId);
    }

    /**
     * 移动文件
     *
     * @param fileId      文件ID
     * @param newParentId 新父文件夹ID，根目录ID由上游使用方定义
     * @param folderId    可选，源文件夹ID，用于获取文件信息
     * @return 移动后的文件信息
     * @throws AuthException 未登录
     * @throws FileException 文件或目标文件夹不存在
     */
    public CloudFile moveFile(String fileId, String newParentId, String folderId) throws AuthException, FileException {
        return client.moveFile(fileId, newParentId, folderId);
    }

    /**
     * 重命名文件
     *
     * @param fileId  文件ID
     * @param newName 新文件名
     * @return 重命名后的文件信息
     * @throws AuthException 未登录
     * @throws FileException 文件不存在
     */
    public CloudFile renameFile(String fileId, String newName) throws AuthException, FileException {
        return client.renameFile(fileId, newName);
    }

    /**
     * 获取文件信息
     * 优化：支持在指定文件夹ID下查看文件信息，查询逻辑是扫描该文件夹下的文件列表，查找指定文件ID的文件
     *
     * @param fileId   文件ID
     * @param folderId 文件夹ID，在该文件夹下查找文件
     * @return 文件信息
     * @throws AuthException 未登录
     * @throws FileException 文件不存在
     */
    public CloudFile getFileInfo(String fileId, String folderId) throws AuthException, FileException {
        return client.getFileInfo(fileId, folderId);
    }

    /**
     * 搜索文件
     *
     * @param parentId 父文件夹ID，根目录ID由上游使用方定义
     * @param query    搜索关键词
     * @return 搜索结果
     * @throws AuthException 未登录
     */
    public List<CloudFile> searchFiles(String parentId, String query) throws AuthException, CloudStorageException {
        return client.searchFiles(parentId, query);
    }

    /**
     * 获取文件下载链接
     *
     * @param fileId 文件ID
     * @return 下载链接
     * @throws AuthException 未登录
     * @throws FileException 文件不存在
     */
    public String getDownloadUrl(String fileId) throws AuthException, FileException, CloudStorageException {
        return client.getDownloadUrl(fileId);
    }

    /**
     * 检查文件是否可以快速上传（秒传）
     *
     * @param fileName 文件名
     * @param fileData 文件数据
     * @return 是否可以快速上传
     * @throws AuthException 未登录
     */
    public boolean checkFastUpload(String fileName, byte[] fileData) throws AuthException {
        return client.checkFastUpload(fileName, fileData);
    }

    /**
     * 快速上传文件（秒传）
     *
     * @param fileName 文件名
     * @param fileData 文件数据
     * @param parentId 父文件夹ID，根目录ID由上游使用方定义
     * @return 上传后的文件信息
     * @throws AuthException         未登录
     * @throws FileException         父文件夹不存在
     * @throws CloudStorageException 快速上传失败
     */
    public CloudFile fastUploadFile(String fileName, byte[] fileData, String parentId)
            throws AuthException, FileException, CloudStorageException {
        return client.fastUploadFile(fileName, fileData, parentId);
    }

    /**
     * 列出回收站文件
     *
     * @return 回收站文件列表
     * @throws AuthException 未登录
     */
    public List<TrashItem> listTrash() throws AuthException {
        return client.listTrash();
    }

    /**
     * 清空回收站
     *
     * @throws AuthException 未登录
     */
    public void emptyTrash() throws AuthException {
        client.emptyTrash();
    }


}